package com.zhang;

import com.zhang.common.codec.MyDecoder;
import com.zhang.common.codec.MyEncoder;
import com.zhang.common.config.GlobalConfig;
import com.zhang.handler.*;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *tcp 客户端 连接
 * @author 98265
 */
public class TCPConnect {

    /**
     * 合并消息的最大长度
     */
    private final static int maxContentLen = Integer.MAX_VALUE;
    /**
     * 日志对象
     */
    static private Logger log = LoggerFactory.getLogger(TCPConnect.class);
    /**
     * ngrok服务器的ip
     */
    private final String ngrokServerIp;
    /**
     * ngrok服务端的端口
     */
    private final int ngrokServerPort ;

    /**
     * 后端真实服务器 启动器
     */
    private static Bootstrap realBootstrap;
    /**
     * 后端真实服务器 线程组
     */
    private EventLoopGroup realGroup;

    /**
     * 客户端 引导器
     */
    private Bootstrap clientBootstrap;

    /**
     * 客户端的 线程组
     */
    private EventLoopGroup clientGroup;

    /**
     * 真实服务的ip  也就是本地服务器 默认是127.0.0.1
     */
    private String realServerIp;
    /**
     * 真实服务器的端口
     */
    private int realServerPort;

    public TCPConnect() {
        //从配置文件中获取端口
        this.realServerPort = GlobalConfig.props.getInt("localport");
        this.realServerIp = GlobalConfig.props.getStr("localdomain","127.0.0.1");
        this.ngrokServerIp = GlobalConfig.props.getStr("serverdomain");
        this.ngrokServerPort = GlobalConfig.props.getInt("serverPort");
        this.realGroup = new NioEventLoopGroup();
        realBootstrap = new Bootstrap();
        this.clientBootstrap = new Bootstrap();
        this.clientGroup = new NioEventLoopGroup();
    }

    /**
     * 连接 ngrok 服务器
     */
    public void connectNgrok() {
        try{
            //初始化连接真实主机的 bootstrap
            connectRealServer();
            clientBootstrap.group(clientGroup);
            clientBootstrap.channel(NioSocketChannel.class);
            clientBootstrap.option(ChannelOption.TCP_NODELAY,true);
            clientBootstrap.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new IdleStateHandler(30,45,60));
                    //tcp编码解码器
//                    ch.pipeline().addLast(new MyCodec());
                    ch.pipeline().addLast("myDecoder",new MyDecoder(Integer.MAX_VALUE,0,4,0,4));
                    ch.pipeline().addLast("myEncoder",new MyEncoder());

                    ch.pipeline().addLast(new RegisterHandler());
                    //心跳
                    ch.pipeline().addLast(new HeartDataHandler());
                    //处理
                    ch.pipeline().addLast(new TCPHandler(realBootstrap,realServerIp,realServerPort));
                    //把请求进行编码
                    ch.pipeline().addLast(new HttpRequestDecoder());
                    ch.pipeline().addLast(new HttpObjectAggregator(maxContentLen));
                    //发送给真实服务器 请求
                    ch.pipeline().addLast(new HttpReceiveHandler());

                }
            });
            ChannelFuture channelFuture = clientBootstrap.connect(ngrokServerIp, ngrokServerPort).sync().addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (future.isSuccess()) {
                        log.info("连接ngrok服务器成功");
                    } else {
                        log.error("连接ngrok服务器失败");
                    }
                }
            });
            channelFuture.channel().closeFuture().addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    log.info("断开连接....");
                    clientGroup.shutdownGracefully();
                    System.exit(0);
                }
            });
        }catch (Exception e){
            log.error("connectNgrok发生异常 err = {}",e);
            clientGroup.shutdownGracefully();
        }
    }

    /**
     * 连接 真实 服务器
     */
    private void connectRealServer() {
        realBootstrap.group(realGroup);
        realBootstrap.channel(NioSocketChannel.class);
        realBootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                //响应解码器
                ch.pipeline().addLast(new HttpResponseDecoder());
                //多个响应合成一个
                ch.pipeline().addLast(new HttpObjectAggregator(maxContentLen));
                //推送给ngrok服务端
                ch.pipeline().addLast(new HttpSendHandler());
            }
        });
    }
}
